package com.lc.driver;

import com.lc.protocol.IFixedTransmitHandler;
import com.lc.protocol.ITransmitHandler;
import com.lc.tool.Convert;

import java.util.Arrays;

/**
 * Created by zhyioo on 2017/3/25.
 */

public class HidFixedTransmitHandler implements ITransmitHandler {

    protected IFixedTransmitHandler _handler = null;

    protected int _fixedIn = 0;

    protected int _fixedOut = 0;

    public HidFixedTransmitHandler() {
    }

    public HidFixedTransmitHandler(IFixedTransmitHandler handler, int fixedIn, int fixedOut) {
        Select(handler, fixedIn, fixedOut);
    }

    public void Select(IFixedTransmitHandler handler, int fixedIn, int fixedOut) {
        _handler = handler;
        _fixedIn = fixedIn;
        _fixedOut = fixedOut;
    }

    @Override
    public boolean OnWrite(byte[] data, int datalen, int timeoutMs) {
        if (_handler == null) {
            return false;
        }
        if (_fixedOut < 1)
            return _handler.OnWrite(data, datalen, timeoutMs);

//        boolean hasSendFixed = false;
//        byte[] block = new byte[Math.max(_handler.GetSendLength(), datalen)];
//        int sendlen = 0;
//        int pkglen = 0;
//        while (sendlen < datalen) {
//            Arrays.fill(block, (byte) 0x00);
//            if (!hasSendFixed) {
//                pkglen = Math.min(_handler.GetSendLength() - _fixedOut, datalen);
//                int len = pkglen;
//                for (int i = _fixedOut - 1; i >= 0; --i) {
//                    block[i] = (byte) (len & 0x0FF);
//                    len >>= 8;
//                }
//                System.arraycopy(data, sendlen, block, _fixedOut, pkglen);
//
//                hasSendFixed = true;
//            } else {
//                for (int i = _fixedOut - 1; i >= 0; --i) {
//                    block[i] = (byte) (pkglen & 0x0FF);
//                    pkglen >>= 8;
//                }
//                pkglen = Math.min(datalen - sendlen, _handler.GetSendLength());
//                System.arraycopy(data, sendlen, block, _fixedOut, pkglen);
//            }
//
//            // 发送失败
//            if (!_handler.OnWrite(block, _handler.GetSendLength(), timeoutMs)) {
//                return false;
//            }
//            sendlen += pkglen;
//        }
        int send = 0;
        int plen = 0;
        byte[] block = new byte[Math.max(_handler.GetSendLength(), datalen)];
        int sLen = (_handler.GetSendLength() - _fixedOut);
        for (; send < datalen / sLen; ++send) {
            Arrays.fill(block, (byte) 0x00);
            plen = _handler.GetSendLength() - _fixedOut;
            int len = plen;
            for (int i = _fixedOut - 1; i >= 0; --i) {
                block[i] = (byte) (plen & 0x0FF);
                plen >>= 8;
            }
            System.arraycopy(data, send * sLen, block, _fixedOut, len);
            block = Convert.StringToHex(Convert.HexToString(block, len + _fixedOut));
            // 发送失败
            if (!_handler.OnWrite(block, block.length, timeoutMs)) {
                return false;
            }
        }
        Arrays.fill(block, (byte) 0x00);
        plen = datalen % sLen;
        int len = plen;
        for (int i = _fixedOut - 1; i >= 0; --i) {
            block[i] = (byte) (plen & 0x0FF);
            plen >>= 8;
        }
        System.arraycopy(data, send * sLen, block, _fixedOut, len);
        block = Convert.StringToHex(Convert.HexToString(block, len + _fixedOut));
        // 发送失败
        if (!_handler.OnWrite(block, block.length, timeoutMs)) {
            return false;
        }
        return true;
    }

    @Override
    public boolean OnRead(byte[] data, int[] datalen, int timeoutMs) {
        if (_handler == null) {
            return false;
        }
        if (_fixedIn < 1)
            return _handler.OnRead(data, datalen, timeoutMs);

        // 预读第一个包
        int[] lenBuff = new int[2];
        byte[] dataBuff = new byte[_handler.GetRecvLength()];

        // 判断是否还有后续的包
        int pkglen = 0;
        if (!_handler.OnRead(dataBuff, lenBuff, timeoutMs)) {
            return false;
        }
        for (int i = 0; i < _fixedIn - 1; ++i) {
            pkglen += (dataBuff[i] << 8);
        }
        pkglen += dataBuff[_fixedIn - 1];
        if (pkglen < 1) {
            return false;
        }
        datalen[0] = pkglen;

        int rlen = _handler.GetRecvLength() - _fixedIn;
        int offset = rlen;
        if (pkglen <= rlen) {
            System.arraycopy(dataBuff, _fixedIn, data, 0, pkglen);
            return true;
        }
        pkglen -= rlen;
        rlen = _handler.GetRecvLength();

        while (pkglen > 0) {
            Arrays.fill(lenBuff, 0);
            if (!_handler.OnRead(dataBuff, lenBuff, timeoutMs)) {
                return false;
            }
            // 已经接收完
            if (pkglen <= rlen) {
                System.arraycopy(dataBuff, 0, data, offset, pkglen);
                break;
            } else {
                System.arraycopy(dataBuff, 0, data, offset, rlen);
            }
            offset += rlen;
        }
        return true;
    }
}
